
// <copyright file="DynamicDAO.Update..cs" company="Subhadra Software Solutions">
//   
// </copyright>
// <summary>
//   The dynamic dao.
// </summary>

namespace SubhadraSolutions.Sharp.Utils.Data.Dynamic
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Diagnostics;
    using System.Linq;

    /// <summary>
    /// The dynamic dao.
    /// </summary>
    /// <typeparam name="E">
    /// </typeparam>
    public static partial class DynamicDAO<E>
    {
        #region Public Methods and Operators

        /// <summary>
        /// The update.
        /// </summary>
        /// <param name="entities">
        /// The entities.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int Update(IEnumerable<E> entities, string tableName = null)
        {
            IDbCommand command = getCommand();
            populateValuesDelegate method = initializeCommandForDml(command, DmlOperationTypes.Update, tableName);
            return executeTransactionCommand(command, entities, false, method);
        }

        /// <summary>
        /// The update.
        /// </summary>
        /// <param name="entities">
        /// The entities.
        /// </param>
        /// <param name="connection">
        /// The connection.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int Update(IEnumerable<E> entities, IDbConnection connection, string tableName = null)
        {
            IDbCommand command = connection.CreateCommand();
            populateValuesDelegate method = initializeCommandForDml(command, DmlOperationTypes.Update, tableName);
            return executeCommand(command, entities, false, method);
        }

        /// <summary>
        /// The update.
        /// </summary>
        /// <param name="entities">
        /// The entities.
        /// </param>
        /// <param name="transaction">
        /// The transaction.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int Update(IEnumerable<E> entities, IDbTransaction transaction, string tableName = null)
        {
            IDbCommand command = transaction.Connection.CreateCommand();
            command.Transaction = transaction;
            populateValuesDelegate method = initializeCommandForDml(command, DmlOperationTypes.Update, tableName);
            return executeCommand(command, entities, false, method);
        }

        /// <summary>
        /// The update.
        /// </summary>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int Update(E entity, string tableName = null)
        {
            IDbCommand command = getCommand();
            using (command.Connection)
            {
                return Update(entity, command, tableName);
            }
        }

        /// <summary>
        /// The update.
        /// </summary>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <param name="connection">
        /// The connection.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int Update(E entity, IDbConnection connection, string tableName = null)
        {
            IDbCommand command = connection.CreateCommand();
            return Update(entity, command, tableName);
        }

        /// <summary>
        /// The update.
        /// </summary>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <param name="command">
        /// The command.
        /// </param>
        /// <param name="tableName">
        /// The table name.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int Update(E entity, IDbCommand command, string tableName = null)
        {
            populateValuesDelegate method = initializeCommandForDml(command, DmlOperationTypes.Update, tableName);
            return updateInsertDelete(entity, command, false, method);
        }

        /// <summary>
        /// The update or Insert.
        /// </summary>
        /// <param name="entities">
        /// The entities.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int UpdateOrInsert(IEnumerable<E> entities)
        {
            IDbConnection connection = getConnection();
            using (connection)
            {
                IDbTransaction transaction = connection.BeginTransaction();
                try
                {
                    int result = UpdateOrInsert(entities, transaction);
                    transaction.Commit();
                    return result;
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex);
                    transaction.Rollback();
                    throw;
                }
            }
        }

        /// <summary>
        /// The update or Insert.
        /// </summary>
        /// <param name="entities">
        /// The entities.
        /// </param>
        /// <param name="connection">
        /// The connection.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int UpdateOrInsert(IEnumerable<E> entities, IDbConnection connection)
        {
            IDbCommand command = connection.CreateCommand();
            int recordsAffected = entities.Sum(entity => updateOrInsert(entity, command));
            return recordsAffected;
        }

        /// <summary>
        /// The update or Insert.
        /// </summary>
        /// <param name="entities">
        /// The entities.
        /// </param>
        /// <param name="transaction">
        /// The transaction.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int UpdateOrInsert(IEnumerable<E> entities, IDbTransaction transaction)
        {
            IDbCommand command = transaction.Connection.CreateCommand();
            command.Transaction = transaction;
            int recordsAffected = entities.Sum(entity => updateOrInsert(entity, command));
            return recordsAffected;
        }

        /// <summary>
        /// The update or Insert.
        /// </summary>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int UpdateOrInsert(E entity)
        {
            IDbConnection connection = getConnection();
            using (connection)
            {
                return UpdateOrInsert(entity, connection);
            }
        }

        /// <summary>
        /// The update or Insert.
        /// </summary>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <param name="connection">
        /// The connection.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int UpdateOrInsert(E entity, IDbConnection connection)
        {
            IDbCommand command = connection.CreateCommand();
            return updateOrInsert(entity, command);
        }

        /// <summary>
        /// The update or Insert.
        /// </summary>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <param name="transaction">
        /// The transaction.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public static int UpdateOrInsert(E entity, IDbTransaction transaction)
        {
            IDbCommand command = transaction.Connection.CreateCommand();
            command.Transaction = transaction;
            return updateOrInsert(entity, command);
        }

        #endregion Public Methods and Operators
    }
}
